import pandas as pd
import numpy as np
import os
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.metrics import mean_absolute_error, mean_squared_error


def load_json_data(filename: str) -> pd.DataFrame:
    """加载JSON数据，处理路径问题和加载错误"""
    current_dir = os.path.dirname(os.path.abspath(__file__))
    file_path = os.path.join(current_dir, "..", "data", filename)
    file_path = os.path.abspath(file_path)

    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            data = pd.read_json(f)
        print(f"成功加载数据: {file_path}，共{len(data)}条记录")
        return data
    except FileNotFoundError:
        print(f"错误: 找不到数据文件 {file_path}")
        return None
    except Exception as e:
        print(f"加载数据时发生错误: {str(e)}")
        return None


# 加载教师数据
df = load_json_data("教师特征及历史教学评价数据.json")

# 检查数据加载是否成功
if df is None or df.empty:
    print("数据加载失败，无法继续执行程序")
    exit(1)

# 检查必要的列是否存在
required_columns = ['age', 'title', 'years_of_experience', 'has_phd',
                    'training_count', 'papers_published', 'teaching_score']
missing_columns = [col for col in required_columns if col not in df.columns]

if missing_columns:
    print(f"错误: 数据中缺少必要的列: {missing_columns}")
    print(f"数据中实际包含的列: {df.columns.tolist()}")
    exit(1)

# 特征和目标变量
numeric_features = ['age', 'years_of_experience', 'has_phd', 'training_count', 'papers_published']
categorical_features = ['title']

# 创建预处理管道（处理分类特征）
preprocessor = ColumnTransformer(
    transformers=[
        ('num', 'passthrough', numeric_features),
        ('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features)
    ])

# 创建模型管道
lr_pipeline = Pipeline(steps=[
    ('preprocessor', preprocessor),
    ('regressor', LinearRegression())
])

gbr_pipeline = Pipeline(steps=[
    ('preprocessor', preprocessor),
    ('regressor', GradientBoostingRegressor(random_state=42))
])

# 准备数据
X = df[numeric_features + categorical_features]
y = df['teaching_score']

# 数据集划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 训练模型
lr_pipeline.fit(X_train, y_train)
gbr_pipeline.fit(X_train, y_train)

# 预测
y_pred_lr = lr_pipeline.predict(X_test)
y_pred_gbr = gbr_pipeline.predict(X_test)

# 评估指标
metrics = {
    "linear_regression": {
        "MAE": round(mean_absolute_error(y_test, y_pred_lr), 3),
        "RMSE": round(np.sqrt(mean_squared_error(y_test, y_pred_lr)), 3),
        "R2": round(lr_pipeline.score(X_test, y_test), 3)
    },
    "gradient_boosting": {
        "MAE": round(mean_absolute_error(y_test, y_pred_gbr), 3),
        "RMSE": round(np.sqrt(mean_squared_error(y_test, y_pred_gbr)), 3),
        "R2": round(gbr_pipeline.score(X_test, y_test), 3)
    }
}

# 获取特征重要性（对于梯度提升树）
feature_names = numeric_features
if hasattr(preprocessor.named_transformers_['cat'], 'get_feature_names_out'):
    feature_names += list(preprocessor.named_transformers_['cat'].get_feature_names_out(categorical_features))

feature_importance = None
if hasattr(gbr_pipeline.named_steps['regressor'], 'feature_importances_'):
    feature_importance = pd.DataFrame({
        "feature": feature_names,
        "importance": gbr_pipeline.named_steps['regressor'].feature_importances_
    }).sort_values("importance", ascending=False)

# 生成未来教师数据
future_teachers = pd.DataFrame({
    'age': [35, 42, 50, 32, 45],
    'title': ['Associate Professor', 'Professor', 'Professor', 'Lecturer', 'Associate Professor'],
    'years_of_experience': [10, 18, 25, 5, 15],
    'has_phd': [1, 1, 1, 0, 1],
    'training_count': [3, 2, 1, 4, 3],
    'papers_published': [12, 25, 30, 5, 18]
})

# 预测未来教师教学评分
future_pred_lr = np.round(lr_pipeline.predict(future_teachers), 2)
future_pred_gbr = np.round(gbr_pipeline.predict(future_teachers), 2)

# 封装结果
teacher_pred_result = {
    "historical_data": df[['teacher_id', 'title', 'teaching_score']].to_dict("records"),
    "metrics": metrics,
    "feature_importance": feature_importance.to_dict("records") if feature_importance is not None else [],
    "future_prediction": {
        "teachers_info": future_teachers.to_dict("records"),
        "lr_prediction": future_pred_lr.tolist(),
        "gbr_prediction": future_pred_gbr.tolist()
    }
}

print("教师教学效果预测模型训练完成")
